package in.muton.edushare.pages.batch;

import in.muton.edushare.auth.roles.UnivRoleCheck;
import in.muton.edushare.pages.EduShareBasePage;
import in.muton.edushare.pages.common.EdusharePanel;
import in.muton.edushare.pages.deptpages.DeptBatches;
import in.muton.edushare.pages.univ.UnivBatches;
import in.muton.edushare.wicket.converters.choicerenderers.GenericRenderer;
import in.muton.edushare.wicket.models.CayenneList;
import in.muton.edushare.wicket.models.CayenneModel;

import java.util.HashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.IModel;

import com.edushare.common.dao.AcademicYearModelDAO;
import com.edushare.common.dao.BatchDAO;
import com.edushare.common.dao.CurriculumDAO;
import com.edushare.common.dao.DepartmentsDAO;
import com.edushare.common.dao.UniversitiesDAO;
import com.edushare.common.vo.AcademicYearModel;
import com.edushare.common.vo.Batches;
import com.edushare.common.vo.Curricula;
import com.edushare.common.vo.Departments;
import com.edushare.common.vo.Universities;
import com.edushare.common.vo.Users;

public class NewBatch extends EdusharePanel {
	private static final long serialVersionUID = 1706751268024375803L;
	private static final Log log = LogFactory.getLog(NewBatch.class);
	private int sourcePageParameter;

	public NewBatch(String id, PageParameters params, EduShareBasePage page){
		//by default it assumes that user arrived from department page
		this(id, params, page, BatchBase.fromDeptPage);
	}
	
	public NewBatch(String id, PageParameters params, EduShareBasePage page, int fromPage) {
		super(id,page);
		init(params);
		this.sourcePageParameter = fromPage;
		grAcad = new GenericRenderer<IModel<AcademicYearModel>>(getAcadMap(),acadModel);
		grCurr = new GenericRenderer<IModel<Curricula>>(getCurrMap(), currModel);
		grYear = new GenericRenderer<Integer>(getYearMap(), batchYear);
		grYear.sort(false);
		grCurr.sort(true);
		loadform();
	}
	
	private void loadform(){
		Form<Void> f = new Form<Void>("newBatchPage");
		add(f);
		f.add(new DropDownChoice<String>("curr", grCurr.getModel(), grCurr
				.getOptions(), grCurr));
		f.add(new DropDownChoice<String>("batchSem", grAcad.getModel(), grAcad
				.getOptions(), grAcad));
		f.add(new DropDownChoice<String>("batchYear", grYear.getModel(), grYear
				.getOptions(), grYear));

		f.add(new Button("save") {
			@Override
			public void onSubmit() {
				if (grYear.getSelection() == null
						|| grCurr.getSelection() == null
						|| grAcad.getSelection() == null) {
					setError("Academic program, starting year and a starting semester are required fields.");
					return;
				}

				int currentSem = new AcademicYearModelDAO(
						getORMInterface(), univModel.getObject())
						.getActiveSemester().getSequenceNo();

				log.debug("Selected year = " + grYear.getSelection());
				log.debug("Selected program = "
						+ grCurr.getSelection().getObject().getCurriculaName());
				log.debug("Selected semester = "
						+ grAcad.getSelection().getObject().getSequenceNo());
				log.debug("Current semester = " + currentSem);
				log.debug("Current year = "
						+ univModel.getObject().getCurrentAcadYear());

				if (grYear.getSelection().intValue() == univModel.getObject()
						.getCurrentAcadYear().intValue()) {
					log.debug("Same year");
					AcademicYearModel aym = grAcad.getSelection().getObject();
					if (aym.getSequenceNo().intValue() > currentSem) {
						log.debug("Same semester");
						setError("You can create a batch that starts in the current or earlier semesters."
								+ "<br/> Batches that start in the future are not allowed.");
						return;
					}
				}

				List<Batches> existingBatches = grCurr.getSelection()
						.getObject().getBatches();
				for (Batches b : existingBatches) {
					if (b.getBatchYear().intValue() == grYear.getSelection()
							.intValue()
							&& b.getStartingSemester().getSequenceNo()
									.intValue() == grAcad.getSelection()
									.getObject().getSequenceNo().intValue()) {
						setError("A batch for this program in this year and semester already exists. Cannot create another batch for the same year and semester.");
						return;
					}
				}

				int semNo = (univModel.getObject().getCurrentAcadYear()
						.intValue() - grYear.getSelection().intValue())
						* univModel.getObject().getAcademicYearModels().size();
				AcademicYearModelDAO ad = new AcademicYearModelDAO(
						getORMInterface(), univModel.getObject());
				semNo += (ad.getActiveSemester().getSequenceNo().intValue());
				semNo -= grAcad.getSelection().getObject().getSequenceNo()
						.intValue();

				log.debug("Calculated semester number for batch = " + semNo);

				if (semNo >= grCurr.getSelection().getObject()
						.getTotalSemester().intValue()) {
					setError("Cannot create batch, as a batch started in "
							+ grAcad.getSelection().getObject()
									.getSemesterName()
							+ " "
							+ grYear.getSelection()
							+ " in would have ended by this semester.");
					return;
				}

				if (batchModel == null) {
					Batches b = new BatchDAO(getORMInterface())
							.startNewBatch(grCurr.getSelection().getObject(),
									semNo, grYear.getSelection(), grAcad
											.getSelection().getObject());
					batchModel = new CayenneModel<Batches>(b);

				} else {
					batchModel.getObject().setBatchYear(grYear.getSelection());
					batchModel.getObject().setCurricula(
							grCurr.getSelection().getObject());
					batchModel.getObject().setCurrentSemester(semNo);
					batchModel.getObject().setStartingSemester(
							grAcad.getSelection().getObject());
					getORMInterface().commitAllChanges();
				}
				PageParameters params = new PageParameters();
				params.put("0", batchModel.getObject().getBatchId().toString());
				params.put("source", sourcePageParameter);
				setResponsePage(BatchPeople.class, params);	
			}

			private static final long serialVersionUID = 8094233215501350908L;
		});

		f.add(new Button("cancel") {
			@Override
			public void onSubmit() {
				setRespPage();
			}

			private static final long serialVersionUID = 2424959207539698204L;
		});
	}
	
	private void setRespPage(){
		PageParameters parameters = new PageParameters();
		if(deptModel != null){
			parameters.put("0", deptModel.getObject().getDeptName());
			parameters.put("1", deptModel.getObject().getDepartmentId().toString());
			setResponsePage(DeptBatches.class, parameters);
		}else{
			parameters.put("0", univModel.getObject().getUniqueName());
			setResponsePage(UnivBatches.class, parameters);
		}
	}

	private HashMap<String, IModel<AcademicYearModel>> getAcadMap() {
		HashMap<String, IModel<AcademicYearModel>> map = new HashMap<String, IModel<AcademicYearModel>>();
		List<AcademicYearModel> acad = univModel.getObject()
				.getAcademicYearModels();
		for (AcademicYearModel a : acad) {
			CayenneModel<AcademicYearModel> c;
			map.put(a.getSemesterName(),
					c = new CayenneModel<AcademicYearModel>(a));
			if (batchModel == null && this.acadModel == null)
				this.acadModel = c;
			else if (batchModel != null)
				this.acadModel = new CayenneModel<AcademicYearModel>(batchModel
						.getObject().getStartingSemester());
		}
		return map;
	}

	private HashMap<String, IModel<Curricula>> getCurrMap() {
		HashMap<String, IModel<Curricula>> map = new HashMap<String, IModel<Curricula>>();
		List<Curricula> currList = getCurriculaList().getUtilList();
		for (Curricula a : currList) {
			CayenneModel<Curricula> c;
			map.put(a.getCurriculaName(), c = new CayenneModel<Curricula>(a));
			if (batchModel == null && this.currModel == null)
				this.currModel = c;
			else if (batchModel != null) {
				this.currModel = new CayenneModel<Curricula>(batchModel
						.getObject().getCurricula());
			}else if(currModel != null && currModel.getObject().getCurriculaId() ==
				a.getCurriculaId()){
				this.currModel = c;
			}
		}
		return map;
	}

	private HashMap<String, Integer> getYearMap() {
		HashMap<String, Integer> map = new HashMap<String, Integer>();
		int currYear = univModel.getObject().getCurrentAcadYear();
		int firstYear = currYear - 8;
		for (int i = currYear; i >= firstYear; i--) {
			map.put(Integer.toString(i), i);
		}
		if (batchModel != null)
			this.batchYear = batchModel.getObject().getBatchYear();
		return map;
	}
	
	private void init(PageParameters params) {
		int univId = params.getAsInteger("0", 0);
		if(univId != 0){
			Universities u = new UniversitiesDAO(getORMInterface()).getUnivById(univId);
			univModel = new CayenneModel<Universities>(u);
		}
		int currId = params.getAsInteger("1", 0);
		if(currId != 0){
			Curricula curr = new CurriculumDAO(getORMInterface()).getCurriculaById(currId);
			currModel = new CayenneModel<Curricula>(curr);
		}
		int batchId = params.getAsInteger("2", 0);
		if(batchId != 0){
			Batches b = new BatchDAO(getORMInterface()).getBatchesById(batchId);
			batchModel = new CayenneModel<Batches>(b);
		}
		int deptId = params.getAsInteger("3", 0);
		if(deptId!=0){
			Departments dept = new DepartmentsDAO(getORMInterface()).getDepartmentByPk(deptId);
			deptModel = new CayenneModel<Departments>(dept);
			if(univModel==null){
				Universities u = new DepartmentsDAO(getORMInterface()).getParent(dept);
				univModel = new CayenneModel<Universities>(u);
			}
		}
	}
	
	public static PageParameters getPageParameters(Batches b, Departments dept, 
			Curricula curr, Universities univ){
		int univId = (univ!=null)?univ.getUniversityId():0;
		int currId = (curr!=null)?curr.getCurriculaId():0;
		int batchId = (b!=null)?b.getBatchId():0;
		int deptId = (dept!=null)?dept.getDepartmentId():0;
		
		PageParameters params = new PageParameters();
		params.put("0", String.valueOf(univId));
		params.put("1", String.valueOf(currId));
		params.put("2", String.valueOf(batchId));
		params.put("3", String.valueOf(deptId));
		return params;
	}

	private CayenneList<Curricula> getCurriculaList() {
		CayenneList<Curricula> currList = new CayenneList<Curricula>(null);
		Users u = getLoggedInUser();
		Universities univ;
		if (univModel == null)
			univ = new DepartmentsDAO(getORMInterface())
					.getParent(deptModel.getObject());
		else
			univ = univModel.getObject();

		UnivRoleCheck urc = new UnivRoleCheck(univ, u);
		if (urc.isAdmin()) {
			currList.add(new CurriculumDAO(getORMInterface())
					.getCurricula(univ));
		} else {
			currList.add(new CurriculumDAO(getORMInterface())
					.getCurriculaByDept(deptModel.getObject()));
		}
		return currList;
	}

	public void setCurrDispName(String currDispName) {
		this.currDispName = currDispName;
	}

	public String getCurrDispName() {
		return currDispName;
	}

	public void setBatchYear(Integer batchYear) {
		this.batchYear = batchYear;
	}

	public Integer getBatchYear() {
		return batchYear;
	}

	private IModel<Departments> deptModel = null;
	private IModel<Universities> univModel = null;
	private IModel<Batches> batchModel = null;
	private String currDispName = "New Batch";
	private Integer batchYear = 0;
	GenericRenderer<IModel<Curricula>> grCurr = null;
	GenericRenderer<IModel<AcademicYearModel>> grAcad = null;
	GenericRenderer<Integer> grYear = null;
	private IModel<Curricula> currModel = null;
	private IModel<AcademicYearModel> acadModel = null;
}
